import logging
import sqlite3
import Sql
import subprocess
import ctypes
import sys
import CSCommunication
from Login import *

##############
#author:张子路#
##############

class Security():
    def __init__(self):
        try:
            self.Communcate=CSCommunication.CSCommunication()
        except Exception as e:
            logging.error("连接文件CSCommunication.py失败 {0}".format(e), exc_info=True)
        try:
            self.Sql=Sql.SqlInformation()
        except Exception as e:
            logging.error("连接文件Sql.py失败 {0}".format(e), exc_info=True)
        try:
            self.conn = sqlite3.connect("./DEMO.db")   #连接数据库
            self.cur = self.conn.cursor()
        except Exception as e:
            logging.error("数据库读取创建出错 {0}".format(e), exc_info=True)
        self.sid={
            'Administrators':'*S-1-5-32-544',
            'Authenticated Users':'*S-1-5-11',
            'Enterprise Domain Controllers':'*S-1-5-9',
            'NT Service':'*S-1-5-80'
        }

    def is_admin(self):
        try:
            return ctypes.windll.shell32.IsUserAnAdmin()
        except:
            return False

    def Export(self):
        cmd='secedit /export /cfg setup.inf'
        try:
            res = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)         #导出注册表
            for line in res.communicate():
                return(line.decode("GBK"))
        except Exception as e:
            logging.error("执行命令失败 {0}".format(e), exc_info=True)

    def __del__(self):
        try:
            self.conn.close()       #销毁对象时关闭数据库
        except Exception:
            print('关闭数据库出错。')
        try:
            self.Sql.CloseSql()      #销毁对象时关闭时关闭数据库
        except Exception:
            print('关闭数据库出错。')

    def SecurityCheck(self):
        self.Export()
        date=[]
        try:
            self.cur.execute('select * from StandrandConfigation')   #获取安全策略标准
        except Exception as e:
            logging.error("数据查询出错 {0},请先执行StandrandSql.py建立标准数据库。".format(e), exc_info=True)
        try:
            for iteam in self.cur.fetchall():
                date.append(['安全策略核查',eval(iteam[1])[0] ,eval(iteam[1])[1] ,eval(iteam[2]),eval(iteam[3]),iteam[4]])
            SearchResult=self.Sql.InSert(date)            #获取安全策略查询结果
        except Exception as e:
            logging.error("数据查询出错 {0}".format(e), exc_info=True)
        Result=[]
        try:
            for iteam in SearchResult:      #根据对比方法检查是否符合规范
                res=''
                adv=''
                cor=True
                cprm=eval(iteam[7])
                cprv=eval(iteam[8])
                if iteam[6]==None:         #当没有设置相应的安全策略时
                    res='当前值未设置，不合格。'
                    cor=False
                    for cpr in range(len(cprm)):    #生成加固建议
                        if cprm[cpr]=='st':
                            adv=adv+'设置值应小于{0};'.format(cprv[cpr])
                        if cprm[cpr]=='bt':
                            adv=adv+'设置值应大于{0};'.format(cprv[cpr])
                        if cprm[cpr]=='equ':
                            adv=adv+'设置值应等于{0};'.format(cprv[cpr])
                        if cprm[cpr]=='not equ':
                            adv=adv+'设置值应不等于{0};'.format(cprv[cpr])
                        if cprm[cpr]=='set to':
                            adv=adv+'设置用有权限的用户应为{0};'.format(cprv[cpr])
                else:
                    for cpr in range(len(cprm)):      #遍历对比方法，对比当前值是否符合规范
                        if cprm[cpr]=='st':
                            adv=adv+'设置值应小于{0};'.format(cprv[cpr])
                            if int(cprv[cpr])<int(iteam[6]):
                                cor=False
                        if cprm[cpr]=='bt':
                            adv=adv+'设置值应大于{0};'.format(cprv[cpr])
                            if int(cprv[cpr])>int(iteam[6]):
                                cor=False
                        if cprm[cpr]=='equ':
                            adv=adv+'设置值应等于{0};'.format(cprv[cpr])
                            if cprv[cpr]!=iteam[6]:
                                cor=False
                        if cprm[cpr]=='not equ':
                            adv=adv+'设置值应不等于{0};'.format(cprv[cpr])
                            if cprv[cpr]==iteam[6]:
                                cor=False
                        if cprm[cpr]=='set to':
                            adv=adv+'设置用有权限的用户应为{0};'.format(cprv[cpr])
                            cuser=iteam[6].split(',')
                            suser=cprv[cpr]
                            for user in cuser:
                                if user not in suser:
                                    cor=False
                            for user in suser:
                                if user not in cuser:
                                    cor=False
                    if cor:
                        res=res+'当前设置值为{0},设置合格。'.format(iteam[6])
                        adv='保持该设置。'
                    else:
                        res=res+'当前设置值为{0},设置不合格。'.format(iteam[6])
                for iteam in self.sid.keys():
                    adv=adv.replace(self.sid[iteam],iteam)
                    res=res.replace(self.sid[iteam],iteam)
                Result.append([iteam[5],res,adv])
        except Exception as e:
            logging.error("生成结果出错 {0}".format(e), exc_info=True)
        try:
            return  Result       #返回结果
        except Exception as e:
            logging.error("输出检测结果出错 {0}".format(e), exc_info=True)

if __name__ == '__main__':
    login=LoginStart()
    login.start()
